home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / misc / coding / midas060 / src / gmpcmds.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-16  |  41.1 KB  |  1,293 lines

  1. /*      gmpcmds.c
  2.  *
  3.  * Generic Module Player command handling
  4.  *
  5.  * $Id: gmpcmds.c,v 1.6 1997/01/16 18:41:59 pekangas Exp $
  6.  *
  7.  * Copyright 1996,1997 Housemarque Inc.
  8.  *
  9.  * This file is part of the MIDAS Sound System, and may only be
  10.  * used, modified and distributed under the terms of the MIDAS
  11.  * Sound System license, LICENSE.TXT. By continuing to use,
  12.  * modify or distribute this file you indicate that you have
  13.  * read the license and understand and accept it fully.
  14. */
  15.  
  16. #include "lang.h"
  17. #include "mtypes.h"
  18. #include "errors.h"
  19. #include "sdevice.h"
  20. #include "gmplayer.h"
  21.  
  22. RCSID(const char *gmpcmds_rcsid = "$Id: gmpcmds.c,v 1.6 1997/01/16 18:41:59 pekangas Exp $";)
  23.  
  24.  
  25.  
  26. /* Commands that support continuing with previous infobyte in case of a zero
  27.    infobyte in pattern data use the infobyte passed as an arguments, others
  28.    just take the value from the channel structure. */
  29.  
  30. /* Protracker-compatible vibrato table: */
  31. static uchar    ptVibratoTable[32] =
  32.     { 0, 24, 49, 74, 97, 120, 141, 161, 180, 197, 212, 224, 235, 244, 250,
  33.       253, 255, 253, 250, 244, 235, 224, 212, 197, 180, 161, 141, 120, 97,
  34.       74, 49, 24 };
  35.  
  36. /* volume fade tables for Retrig Note: */
  37. static signed char retrigTable1[16] =
  38.     { 0, 0, 0, 0, 0, 0, 10, 8, 0, 0, 0, 0, 0, 0, 24, 32 };
  39.  
  40. static signed char retrigTable2[16] =
  41.     { 0, -1, -2, -4, -8, -16, 0, 0, 0, 1, 2, 4, 8, 16, 0, 0 };
  42.  
  43.  
  44.  
  45.  
  46. /* No command: */
  47. static int gmpCmdEmpty(void)
  48. {
  49.     return OK;
  50. }
  51.  
  52.  
  53. /* Set speed: */
  54. static int gmpCmdSetSpeed(void)
  55. {
  56.     if (gmpChan->infobyte != 0 )
  57.         gmpHandle->speed = gmpChan->infobyte;
  58.     else
  59.     {
  60.         switch ( gmpPlayMode )
  61.         {
  62.             case gmpST3:
  63.                 break;
  64.  
  65.             default:
  66.                 /* Restart song */
  67.  
  68.                 gmpHandle->position = gmpHandle->restartPos;
  69.  
  70.                 /* Get the pattern number for new position: */
  71.                 gmpHandle->pattern = gmpCurModule->songData[gmpHandle->position];
  72.  
  73.                 /* Set pattern data pointer to NULL to mark playing position
  74.                     has changed: */
  75.                 gmpHandle->playPtr = NULL;
  76.                 gmpHandle->row = 0;
  77.                 break;
  78.         }
  79.     }
  80.     return OK;
  81. }
  82.  
  83.  
  84. /* Set tempo in BPM: */
  85. static int gmpCmdSetTempo(void)
  86. {
  87.     /* We will just ignore tempos below 32 - ST3 and FT2 do that and with PT
  88.        you just can't set tempos below that */
  89.     if ( gmpChan->infobyte < 32 )
  90.         return OK;
  91.  
  92.     return gmpSetTempo(gmpChan->infobyte);
  93. }
  94.  
  95.  
  96. /* Set volume: */
  97. static int gmpCmdSetVolume(void)
  98. {
  99.     return gmpSetVolume(gmpChan->infobyte);
  100. }
  101.  
  102. /* Set master volume: */
  103. static int gmpCmdSetMVolume(void)
  104. {
  105.     gmpHandle->masterVolume = gmpChan->infobyte;
  106.     if ( gmpHandle->masterVolume > 64 )
  107.         gmpHandle->masterVolume = 64;
  108.     return OK;
  109. }
  110.  
  111. /* Set panning: */
  112. static int gmpCmdSetPanning(void)
  113. {
  114.     return gmpSetPanning(gmpChan->infobyte);
  115. }
  116.  
  117.  
  118. /* Volume slide: */
  119. static int gmpCmdVolSlide(unsigned infobyte)
  120. {
  121.     switch ( gmpPlayMode )
  122.     {
  123.         case gmpST3:
  124.             if ( ((infobyte & 0x0F) == 0x0F) && ((infobyte & 0xF0) != 0) )
  125.             {
  126.                 /* The lower nybble is 0xF, and the upper nybble is nonzero
  127.                    - fine volume slide up (if the upper nybble is zero, ST3
  128.                    does a normal volume slide down with speed 0xF) */
  129.  
  130.                 if ( gmpHandle->playCount == 0 )
  131.                     return gmpSetVolume(gmpChan->volume +
  132.                         (infobyte >> 4));
  133.                 else
  134.                     return OK;
  135.             }
  136.  
  137.             if ( ((infobyte & 0xF0) == 0xF0) && ((infobyte & 0x0F) != 0) )
  138.             {
  139.                 /* The upper nybble is 0xF and the lower nybble is nonzero
  140.                    - fine volume slide down (if the lower nybble is zero, ST3
  141.                    does a normal volume slide up with speed 0xF) */
  142.                 if ( gmpHandle->playCount == 0 )
  143.                     return gmpSetVolume((int)gmpChan->volume -
  144.                         (int)(infobyte & 0x0F));
  145.                 else
  146.                     return OK;
  147.             }
  148.  
  149.             /* We are doing a normal volume slide */
  150.  
  151.             if ( (infobyte & 0x0F) != 0 )
  152.             {
  153.                 /* The lower nybble is set - do a volume slide down */
  154.                 /* Note! ST3 does the check in _this_ order, PT and FT2 the
  155.                    other way around! */
  156.  
  157.                 if ( (gmpCurModule->playFlags.fastVolSlides) ||
  158.                      (gmpHandle->playCount != 0) )
  159.                     return gmpSetVolume((int)gmpChan->volume -
  160.                         (int)(infobyte & 0x0F));
  161.                     else
  162.                         return OK;
  163.             }
  164.  
  165.             /* The lower nybble was not set - do a volume slide up: */
  166.             if ( (gmpCurModule->playFlags.fastVolSlides) ||
  167.                  (gmpHandle->playCount != 0) )
  168.                 return gmpSetVolume(gmpChan->volume + (infobyte >> 4));
  169.  
  170.             return OK;
  171.  
  172.         case gmpFT2:
  173.             /* FT2 playing mode - if the infobyte is zero, use the old
  174.                volume slide infobyte */
  175.             if ( !infobyte )
  176.                 infobyte = gmpChan->volSlideInfobyte;
  177.             else
  178.                 gmpChan->volSlideInfobyte = infobyte;
  179.  
  180.             /* FALL THROUGH to combined PT and FT2 volume slide code! */
  181.  
  182.         default:
  183.             /* The volume slide for PT and FT2 */
  184.  
  185.             if ( (infobyte & 0xF0) != 0 )
  186.             {
  187.                 /* The upper nybble is set - do volume slide up */
  188.                 /* Note! We don't need to check the play count as this command
  189.                    won't be called on 0-ticks */
  190.                 return gmpSetVolume(gmpChan->volume + (infobyte >> 4));
  191.             }
  192.  
  193.             /* Do volume slide down: */
  194.             return gmpSetVolume((int)gmpChan->volume - (int)(infobyte & 0xF));
  195.     }
  196. }
  197.  
  198.  
  199. /* Master volume slide: */
  200. static int gmpCmdMVolSlide(unsigned infobyte)
  201. {
  202.     int         newMasterVol = gmpHandle->masterVolume;
  203.  
  204.     if ( (infobyte & 0xF0) != 0 )
  205.     {
  206.         /* The upper nybble is set - slide up */
  207.         newMasterVol += (int) (infobyte >> 4);
  208.     }
  209.     else
  210.     {
  211.         /* Slide down: */
  212.         newMasterVol -= (int) (infobyte & 0x0F);
  213.     }
  214.  
  215.     /* Clip master volume: */
  216.     if ( newMasterVol < 0 )
  217.         newMasterVol = 0;
  218.     if ( newMasterVol > 64 )
  219.         newMasterVol = 64;
  220.  
  221.     gmpHandle->masterVolume = newMasterVol;
  222.  
  223.     return OK;
  224. }
  225.  
  226.  
  227. /* Fine volume slide up: */
  228. static int gmpCmdFineVolSlideUp(unsigned infobyte)
  229. {
  230.     return gmpSetVolume(gmpChan->volume + infobyte);
  231. }
  232.  
  233.  
  234. /* Fine volume slide down */
  235. static int gmpCmdFineVolSlideDown(unsigned infobyte)
  236. {
  237.     return gmpSetVolume((int)gmpChan->volume - (int)infobyte);
  238. }
  239.  
  240.  
  241. /* Panning slide: */
  242. static int gmpCmdPanSlide(unsigned infobyte)
  243. {
  244.     if ( (infobyte & 0xF0) != 0 )
  245.     {
  246.         /* Upper nybble is nonzero - slide right */
  247.         return gmpSetPanning(gmpChan->panning + (infobyte >> 4));
  248.     }
  249.  
  250.     /* Upper nybble is zero - slide left: */
  251.     return gmpSetPanning((int) gmpChan->panning - (int) (infobyte & 0x0F));
  252. }
  253.  
  254.  
  255. /* Period slide up: */
  256. static int gmpCmdSlideUp(unsigned infobyte)
  257. {
  258.     if ( gmpPlayMode == gmpST3 )
  259.     {
  260.         if ( infobyte < 0xE0 )
  261.         {
  262.             if ( gmpHandle->playCount != 0 )
  263.                 return gmpSetPeriod(gmpChan->period - (((int) infobyte) <<
  264.                     gmpHandle->perMultiplier));
  265.             else
  266.                 return OK;
  267.         }
  268.         else
  269.         {
  270.             if ( gmpHandle->playCount == 0 )
  271.             {
  272.                 if ( infobyte < 0xF0 )
  273.                     return gmpSetPeriod(gmpChan->period - (infobyte & 0xF));
  274.                 else
  275.                     return gmpSetPeriod(gmpChan->period -
  276.                         (((int) infobyte & 0xF) << gmpHandle->perMultiplier));
  277.             }
  278.             else
  279.                 return OK;
  280.         }
  281.     }
  282.     else
  283.         return gmpSetPeriod(gmpChan->period - (((int) infobyte) <<
  284.             gmpHandle->perMultiplier));
  285. }
  286.  
  287.  
  288. /* Period slide down: */
  289. static int gmpCmdSlideDown(unsigned infobyte)
  290. {
  291.     if ( gmpPlayMode == gmpST3 )
  292.     {
  293.         if ( infobyte < 0xE0 )
  294.         {
  295.             if ( gmpHandle->playCount != 0 )
  296.                 return gmpSetPeriod(gmpChan->period + (((int) infobyte) <<
  297.                     gmpHandle->perMultiplier));
  298.             else
  299.                 return OK;
  300.         }
  301.         else
  302.         {
  303.             if ( gmpHandle->playCount == 0 )
  304.             {
  305.                 if ( infobyte < 0xF0 )
  306.                     return gmpSetPeriod(gmpChan->period + (infobyte & 0xF));
  307.                 else
  308.                     return gmpSetPeriod(gmpChan->period +
  309.                         (((int) infobyte & 0xF) << gmpHandle->perMultiplier));
  310.             }
  311.             else
  312.                 return OK;
  313.         }
  314.     }
  315.     else
  316.         return gmpSetPeriod(gmpChan->period + (((int) infobyte) <<
  317.             gmpHandle->perMultiplier));
  318. }
  319.  
  320.  
  321. /* Fine period slide up: */
  322. static int gmpCmdFineSlideUp(unsigned infobyte)
  323. {
  324.     return gmpSetPeriod(gmpChan->period - (((int) infobyte) <<
  325.         gmpHandle->perMultiplier));
  326. }
  327.  
  328.  
  329. /* Fine period slide down: */
  330. static int gmpCmdFineSlideDown(unsigned infobyte)
  331. {
  332.     return gmpSetPeriod(gmpChan->period - (((int) infobyte) >>
  333.         gmpHandle->perMultiplier));
  334. }
  335.  
  336.  
  337. /* Extra fine period slide up: */
  338. static int gmpCmdExtraFineSlideUp(unsigned infobyte)
  339. {
  340.     return gmpSetPeriod((int)gmpChan->period - (int)infobyte);
  341. }
  342.  
  343.  
  344. /* Extra fine period slide down: */
  345. static int gmpCmdExtraFineSlideDown(unsigned infobyte)
  346. {
  347.     return gmpSetPeriod(gmpChan->period + infobyte);
  348. }
  349.  
  350.  
  351. /* Do the actual tone portamento */
  352. static int doTonePortamento(unsigned infobyte)
  353. {
  354.     unsigned    tpSpeed;
  355.  
  356.     /* Skip if portamento destination is zero: */
  357.     if ( gmpChan->tpDest == 0 )
  358.         return OK;
  359.  
  360.     /* If command infobyte is not zero, use it as new tone portamento speed: */
  361.     if ( infobyte != 0 )
  362.         gmpChan->tpSpeed = infobyte;
  363.  
  364.     /* Skip if channel period already equals tone portamento destination: */
  365.     if ( gmpChan->period == gmpChan->tpDest )
  366.         return OK;
  367.  
  368.     tpSpeed = ((unsigned) gmpChan->tpSpeed) << gmpHandle->perMultiplier;
  369.  
  370.     if ( gmpChan->period < gmpChan->tpDest )
  371.     {
  372.         /* Period is below tone portamento destination - check if we'd reach
  373.            the portamento destination this time. If yes, set the tone
  374.            portamento destination as new period, otherwise just increase
  375.            the period: */
  376.         if ( (gmpChan->period + tpSpeed) >= gmpChan->tpDest )
  377.             return gmpSetPeriod(gmpChan->tpDest);
  378.         else
  379.             return gmpSetPeriod(gmpChan->period + tpSpeed);
  380.     }
  381.     else
  382.     {
  383.         /* Period is above tone portamento destination. Check if we'd reach
  384.            the destination this time, and if so, set the destination as the
  385.            new period. Otherwise just decrease the period: */
  386.         if ( (gmpChan->period - gmpChan->tpDest) <= tpSpeed)
  387.             return gmpSetPeriod(gmpChan->tpDest);
  388.         else
  389.             return gmpSetPeriod(gmpChan->period - tpSpeed);
  390.     }
  391. }
  392.  
  393.  
  394. /* Tone portamento: */
  395. static int gmpCmdTonePortamento(void)
  396. {
  397.     return doTonePortamento(gmpChan->infobyte);
  398. }
  399.  
  400.  
  401. /* Set tone portamento: */
  402. static int gmpCmdSetTonePorta(void)
  403. {
  404.     int         error;
  405.  
  406.     /* If there is a new note, set its period as tone portamento destination
  407.        and clear the new note flag so that the sound won't be retrigged: */
  408.     if ( (gmpChan->status.newNote) && (gmpChan->instrument != -1)
  409.         && (gmpChan->sample != 0xFF) && ( gmpChan->note != 0xFE ))
  410.     {
  411.         if ( (error = gmpNotePeriod(gmpChan->note, &gmpChan->tpDest))
  412.             != OK )
  413.             return error;
  414.         gmpChan->status.newNote = 0;
  415.     }
  416.  
  417.     return OK;
  418. }
  419.  
  420.  
  421. /* Tone Portamento + Volume Slide: */
  422. static int gmpCmdTPortVSlide(unsigned infobyte)
  423. {
  424.     int         error;
  425.  
  426.     /* Do the volume slide using current infobyte: */
  427.     if ( (error = gmpCmdVolSlide(infobyte)) != OK )
  428.         return error;
  429.  
  430.     /* Do the tone portamento using previous portamento speed: */
  431.     return doTonePortamento(0);
  432. }
  433.  
  434.  
  435. /* Do vibrato command: */
  436. static int doVibrato(unsigned infobyte)
  437. {
  438.     unsigned    vibPer;
  439.     int         error;
  440.  
  441.     /* If infobyte lower nybble is nonzero, use it as new vibrato depth: */
  442.     if ( (infobyte & 0x0F) != 0 )
  443.         gmpChan->vibDepth = infobyte & 0x0F;
  444.  
  445.     /* If infobyte upper nybble is nonzero, use it as new vibrato speed: */
  446.     if ( (infobyte & 0xF0) != 0 )
  447.         gmpChan->vibSpeed = infobyte >> 4;
  448.  
  449.     /* Get vibrato value from vibrato table and scale it with the vibrato
  450.        depth: */
  451.     vibPer = (((unsigned) ptVibratoTable[gmpChan->vibPos & 31]) *
  452.         ((unsigned) gmpChan->vibDepth)) >> (7 - gmpHandle->perMultiplier);
  453.  
  454.     /* If vibrato position bit 5 is 0, add value to period, otherwise
  455.        substract it: */
  456.     if ( (gmpChan->vibPos & 32) == 0 )
  457.         error = gmpChangePeriod(gmpChan->period + vibPer);
  458.     else
  459.         error = gmpChangePeriod(gmpChan->period - vibPer);
  460.  
  461.     /* Update vibrato position: */
  462.     gmpChan->vibPos += gmpChan->vibSpeed;
  463.  
  464.     return error;
  465. }
  466.  
  467.  
  468. /* Vibrato: */
  469. static int gmpCmdVibrato(void)
  470. {
  471.     return doVibrato(gmpChan->infobyte);
  472. }
  473.  
  474.  
  475. /* Vibrato and volume slide: */
  476. static int gmpCmdVibVSlide(unsigned infobyte)
  477. {
  478.     int         error;
  479.  
  480.     /* Do the volume slide using current infobyte: */
  481.     if ( (error = gmpCmdVolSlide(infobyte)) != OK )
  482.         return error;
  483.  
  484.     /* Do the vibrato using previous values: */
  485.     return doVibrato(0);
  486. }
  487.  
  488.  
  489. /* Sample Offset: */
  490. static int gmpCmdSampleOffset(void)
  491. {
  492.     int         error;
  493.     unsigned    soAdd;
  494.  
  495.     /* If infobyte is nonzero, use it as new sample offset value: */
  496.     if ( gmpChan->infobyte != 0 )
  497.         gmpChan->smpOffset = gmpChan->infobyte;
  498.  
  499.     /* Calculate sample offset in bytes: */
  500.     soAdd = ((unsigned) gmpChan->smpOffset) << 8;
  501.  
  502.     /* Check if there is a new note: */
  503.     if ( gmpChan->status.newNote )
  504.     {
  505.         /* Increase new note start offset: */
  506.         gmpChan->startOffset += soAdd;
  507.  
  508.         /* Play the note: */
  509.         if ( (error = gmpNewNote()) != OK )
  510.             return error;
  511.     }
  512.  
  513.     /* Now increase new note start offset again - next note will be
  514.        started from 2*sampleoffset unless a new instrument is set:
  515.        (Protracker "feature") */
  516.     if ( gmpPlayMode == gmpPT)
  517.         gmpChan->startOffset += soAdd;
  518.  
  519.     return OK;
  520. }
  521.  
  522.  
  523. /* Set note retrig count: (retrig note on tick 0) */
  524. static int gmpCmdSetRetrig(void)
  525. {
  526.     gmpChan->retrigCount = 1;
  527.     return OK;
  528. }
  529.  
  530.  
  531. /* Retrig note: */
  532. static int gmpCmdRetrigNote(unsigned infobyte)
  533. {
  534.     int         error;
  535.  
  536.     /* FIXME! */
  537.     if ( gmpPlayMode == gmpST3 )
  538.         gmpChan->infobyte = infobyte;
  539.  
  540.     /* No retrig if channel infobyte is zero: */
  541.     if ( gmpChan->infobyte != 0 )
  542.     {
  543.         /* Check if note needs to be retriggered: */
  544.         if ( gmpChan->retrigCount >= (gmpChan->infobyte & 0xF) )
  545.         {
  546.             /* Retrig note - set playing position to startOffset: */
  547.             if ( (error = gmpSD->SetPosition(gmpChan->sdChannel,
  548.                 gmpChan->startOffset)) != OK )
  549.                 return error;
  550.  
  551.             /* Reset retrig counter: */
  552.             gmpChan->retrigCount = 0;
  553.         }
  554.     }
  555.  
  556.     /* Increase retrig counter: */
  557.     gmpChan->retrigCount++;
  558.  
  559.     return OK;
  560. }
  561.  
  562.  
  563. /* ST3 Retrig note: */
  564. static int gmpCmdS3MRetrig(unsigned infobyte)
  565. {
  566.     int         error, i;
  567.  
  568.     /* No retrig if channel infobyte is zero: */
  569.  
  570.     /* Check if note needs to be retriggered: */
  571.     if ( gmpChan->retrigCount >= (infobyte & 0xF) )
  572.     {
  573.         /* Retrig note - set playing position to startOffset: */
  574.         if ( (error = gmpSD->SetPosition(gmpChan->sdChannel,
  575.             gmpChan->startOffset)) != OK )
  576.             return error;
  577.  
  578.         /* Reset retrig counter: */
  579.         gmpChan->retrigCount = 0;
  580.  
  581.  
  582.         i = ( infobyte & 0xf0 ) >> 4;
  583.         if ( retrigTable1[i] == 0 )
  584.             i = gmpChan->volume + retrigTable2[i];
  585.         else
  586.             i = ( gmpChan->volume * retrigTable1[i] ) >> 4;
  587.  
  588.         error = gmpSetVolume( i );
  589.         if ( error != OK )
  590.             return error;
  591.     }
  592.  
  593.     /* Increase retrig counter: */
  594.     gmpChan->retrigCount++;
  595.     return OK;
  596. }
  597.  
  598.  
  599. /* Position Jump: */
  600. static int gmpCmdPositionJump(void)
  601. {
  602.     /* Break to next position: */
  603.     gmpHandle->position = (unsigned)gmpChan->infobyte;
  604.  
  605.     /* Check if we reached song length, and if so, jump to restart
  606.         position: */
  607.     if ( gmpHandle->position > gmpHandle->songEnd )
  608.     {
  609.         gmpHandle->position = gmpHandle->restartPos;
  610.     }
  611.  
  612.     /* Get the pattern number for new position: */
  613.     gmpHandle->pattern = gmpCurModule->songData[gmpHandle->position];
  614.  
  615.     /* Set pattern data pointer to NULL to mark playing position
  616.         has changed: */
  617.     gmpHandle->playPtr = NULL;
  618.  
  619.     gmpHandle->row = 0;
  620.  
  621.     /* Reset pattern loop destination row if playing ST3 module: */
  622.     if ( gmpPlayMode == gmpST3 )
  623.         gmpHandle->loopRow = 0;
  624.  
  625.     return OK;
  626. }
  627.  
  628. /* Pattern Break: */
  629. static int gmpCmdPatternBreak(void)
  630. {
  631.     if ( gmpHandle->playPtr != NULL )
  632.     {
  633.         /* Go to next position skipping S3M song data filler: */
  634.         do
  635.         {
  636.             gmpHandle->position++;
  637.  
  638.             /* Check if we reached song length, and if so, jump to restart
  639.                 position: */
  640.             if ( (gmpHandle->position > gmpHandle->songEnd) ||
  641.                 (gmpCurModule->songData[gmpHandle->position] == 0xffff))
  642.             {
  643.                 gmpHandle->position = gmpHandle->restartPos;
  644.             }
  645.         } while ( gmpCurModule->songData[gmpHandle->position] == 0xfffe );
  646.  
  647.         /* Get the pattern number for new position: */
  648.         gmpHandle->pattern = gmpCurModule->songData[gmpHandle->position];
  649.  
  650.         /* Set pattern data pointer to NULL to mark playing position
  651.             has changed: */
  652.         gmpHandle->playPtr = NULL;
  653.  
  654.         /* Reset pattern loop destination row if playing ST3 module: */
  655.         if ( gmpPlayMode == gmpST3 )
  656.             gmpHandle->loopRow = 0;
  657.     }
  658.  
  659.     /* infobyte is new row number: (IN BCD FORMAT!) */
  660.     if ( gmpChan->infobyte <= 0x63 )
  661.         gmpHandle->row = (gmpChan->infobyte & 0x0F) +
  662.         ((gmpChan->infobyte >> 4) * 10);
  663.     else
  664.         gmpHandle->row = 63;
  665.  
  666.     return OK;
  667. }
  668.  
  669.  
  670. /* Note Cut: */
  671. static int gmpCmdNoteCut(void)
  672. {
  673.     /* Cut note by setting volume to zero if play counter equals infobyte: */
  674.     if ( gmpHandle->playCount == gmpChan->infobyte )
  675.         return gmpSetVolume(0);
  676.     else
  677.         return OK;
  678. }
  679.  
  680.  
  681. /* Set Note Delay: (Note Delay at tick 0) */
  682. static int gmpCmdSetNoteDelay(void)
  683. {
  684.     /* If infobyte is 0 or there is no new note, play normally: */
  685.     if ( (gmpChan->infobyte == 0) || (!gmpChan->status.newNote) )
  686.     {
  687.         gmpChan->status.noteDelay = 0;      /* no note delay */
  688.         return OK;
  689.     }
  690.  
  691.     /* Mark there is a valid new note for note delay, and do not play it
  692.        normally: */
  693.     gmpChan->status.noteDelay = 1;
  694.     gmpChan->status.newNote = 0;
  695.     return OK;
  696. }
  697.  
  698.  
  699. /* Note Delay: */
  700. static int gmpCmdNoteDelay(void)
  701. {
  702.     /* If infobyte equals player counter and there is a valid new note for
  703.        note delay, start the new note: */
  704.     if ( (gmpHandle->playCount == gmpChan->infobyte) &&
  705.         (gmpChan->status.noteDelay) )
  706.     {
  707.         return gmpNewNote();
  708.     }
  709.  
  710.     return OK;
  711. }
  712.  
  713.  
  714. /* Pattern Delay: */
  715. static int gmpCmdPatternDelay(void)
  716. {
  717.     /* Set pattern delay counter to infobyte if pattern delay is not in
  718.        progress: */
  719.     if ( gmpHandle->pattDelayCount == 0 )
  720.         gmpHandle->pattDelayCount = gmpChan->infobyte;
  721.     return OK;
  722. }
  723.  
  724.  
  725.  
  726. /* Set 16-point panning value: */
  727. static int gmpCmdSetPanning16(void)
  728. {
  729.     int         panValue;
  730.  
  731.     panValue = gmpChan->infobyte;
  732.     if ( panValue < 7 )
  733.     {
  734.         panValue = 8 * panValue;
  735.     }
  736.     else
  737.     {
  738.         if ( panValue > 8 )
  739.             panValue = 0x80 - (15 - panValue) * 8;
  740.         else
  741.             panValue = 0x40;
  742.     }
  743.  
  744.     return gmpSetPanning(panValue);
  745. }
  746.  
  747.  
  748. /* Arpeggio: */
  749. static int gmpCmdArpeggio(unsigned infobyte)
  750. {
  751.     static unsigned newPeriod;
  752.     int         error;
  753.     int         note = gmpChan->note & 0x0F;
  754.     int         oct = (gmpChan->note >> 4) & 0x0F;
  755.  
  756.     /* Make sure that we have a valid instrument: */
  757.     if ( (gmpChan->instrument != -1) && (gmpChan->sample != 0xFF) )
  758.     {
  759.         /* Check that current note is not key off: */
  760.         if ( gmpChan->note == 0xFE )
  761.             return OK;
  762.  
  763.         /* Add correct infobyte nybble to note number: */
  764.         switch ( gmpHandle->playCount % 3 )
  765.         {
  766.             case 0:
  767.                 break;
  768.  
  769.             case 1:
  770.                 note += (infobyte >> 4) & 0x0F;
  771.                 break;
  772.  
  773.             case 2:
  774.                 note += infobyte & 0x0F;
  775.                 break;
  776.         }
  777.  
  778.         /* Update octave if necessary: */
  779.         if ( note > 11 )
  780.         {
  781.             oct++;
  782.             note -= 12;
  783.         }
  784.  
  785.         if ( (gmpPlayMode == gmpPT) && (!gmpCurModule->playFlags.extOctaves) )
  786.         {
  787.             /* Playing a Protracker module with extended octaves disabled -
  788.                take care of arpeggio wrap: */
  789.             if ( oct > 3 )
  790.                 oct -= 3;
  791.             /* Actually we should increment finetune here and play random
  792.                trash if finetune was 0x0F... */
  793.         }
  794.  
  795.         note |= oct << 4;
  796.  
  797.         /* Get new note period value: */
  798.         if ( (error = gmpNotePeriod(note, &newPeriod)) != OK )
  799.             return error;
  800.  
  801.         /* Set new period value: */
  802.         if ( (error = gmpChangePeriod(newPeriod)) != OK )
  803.             return error;
  804.     }
  805.  
  806.     return OK;
  807. }
  808.  
  809.  
  810.  
  811. /* Music synchronization: */
  812. static int gmpCmdMusicSync(void)
  813. {
  814.     /* Set synchronization info to handle: */
  815.     gmpHandle->syncInfo = gmpChan->infobyte;
  816.  
  817.     /* Call music synchronization callback function if set: */
  818.     if ( gmpHandle->SyncCallback != NULL )
  819.     {
  820.         gmpHandle->SyncCallback(gmpChan->infobyte, gmpHandle->position,
  821.             gmpHandle->row);
  822.     }
  823.  
  824.     return OK;
  825. }
  826.  
  827.  
  828.  
  829. static int gmpCmdPatternLoop(void)
  830. {
  831.     uchar       info = gmpChan->infobyte;
  832.     int         jump = -1;
  833.  
  834.     /* Pattern loop is handled differently for Scream Tracker 3 modules -
  835.        in PT and FT2 modules each channel has its own pattern loop info and
  836.        the loops can be nested, while in ST3 the values are global for the
  837.        whole song. Also, in ST3 the pattern loop destination row is reset
  838.        to zero for each new pattern, while in PT and FT2 the values from
  839.        the previous pattern are used. */
  840.     if ( gmpPlayMode == gmpST3 )
  841.     {
  842.         if ( info == 0 )
  843.         {
  844.             /* Infobyte = 0 - set pattern loop start row: */
  845.             gmpHandle->loopRow = gmpHandle->row;
  846.         }
  847.         else
  848.         {
  849.             /* Infobyte != 0 - set loop count if not already looping: */
  850.             if ( gmpHandle->loopCount == 0 )
  851.             {
  852.                 gmpHandle->loopCount = info;
  853.                 jump = gmpHandle->loopRow;
  854.             }
  855.             else
  856.             {
  857.                 /* Already looping - jump to loop start if loop counter
  858.                    is not yet zero: */
  859.                 gmpHandle->loopCount--;
  860.                 if ( gmpHandle->loopCount > 0 )
  861.                     jump = gmpHandle->loopRow;
  862.             }
  863.         }
  864.     }
  865.     else
  866.     {
  867.         if ( info == 0 )
  868.         {
  869.             /* Infobyte = 0 - set pattern loop start row: */
  870.             gmpChan->loopRow = gmpHandle->row;
  871.         }
  872.         else
  873.         {
  874.             /* Infobyte != 0 - set loop count if not already looping: */
  875.             if ( gmpChan->loopCount == 0 )
  876.             {
  877.                 gmpChan->loopCount = info;
  878.                 jump = gmpChan->loopRow;
  879.             }
  880.             else
  881.             {
  882.                 /* Already looping - jump to loop start if loop counter
  883.                    is not yet zero: */
  884.                 gmpChan->loopCount--;
  885.                 if ( gmpChan->loopCount > 0 )
  886.                     jump = gmpChan->loopRow;
  887.             }
  888.         }
  889.     }
  890.  
  891.     /* Jump to loop start row if necessary: */
  892.     if ( jump != -1 )
  893.     {
  894.         gmpHandle->row = jump;
  895.         gmpHandle->playPtr = NULL;
  896.     }
  897.  
  898.     return OK;
  899. }
  900.  
  901.  
  902.  
  903.  
  904.  
  905. /****************************************************************************\
  906. *
  907. * Function:     int gmpSetVolCommand(void)
  908. *
  909. * Description:  Runs tick-0 volume column command for current channel (FT2)
  910. *
  911. * Returns:      MIDAS error code
  912. *
  913. \****************************************************************************/
  914.  
  915. int gmpSetVolCommand(void)
  916. {
  917.     int         infobyte = gmpChan->volColumn & 0x0F;
  918.  
  919.     switch ( gmpChan->volColumn & 0xF0 )
  920.     {
  921.         case 0x80:
  922.             /* Fine volume slide down: */
  923.             return gmpSetVolume(gmpChan->volume - infobyte);
  924.  
  925.         case 0x90:
  926.             /* Fine volume slide up: */
  927.             return gmpSetVolume(gmpChan->volume + infobyte);
  928.  
  929.         case 0xA0:
  930.             /* Set vibrato speed: */
  931.             gmpChan->vibSpeed = infobyte;
  932.             break;
  933.  
  934.         case 0xC0:
  935.             /* Set panning: */
  936.             return gmpSetPanning(infobyte | (infobyte << 4));
  937.             break;
  938.  
  939.         case 0xF0:
  940.             /* Tone portamento: */
  941.             return gmpCmdSetTonePorta();
  942.             break;
  943.     }
  944.  
  945.     return OK;
  946. }
  947.  
  948. /*
  949.       0       Do nothing
  950.     $10-$50   Set volume Value-$10
  951.       :          :        :
  952.       :          :        :
  953.     $60-$6f   Volume slide down
  954.     $70-$7f   Volume slide up
  955.     $80-$8f   Fine volume slide down
  956.     $90-$9f   Fine volume slide up
  957.     $a0-$af   Set vibrato speed
  958.     $b0-$bf   Vibrato
  959.     $c0-$cf   Set panning
  960.     $d0-$df   Panning slide left
  961.     $e0-$ef   Panning slide right
  962.     $f0-$ff   Tone porta
  963. */
  964.  
  965.  
  966. /****************************************************************************\
  967. *
  968. * Function:     int gmpRunVolCommand(void)
  969. *
  970. * Description:  Runs continuous volume column command for current channel
  971. *
  972. * Returns:      MIDAS error code
  973. *
  974. \****************************************************************************/
  975.  
  976. int gmpRunVolCommand(void)
  977. {
  978.     int         infobyte = gmpChan->volColumn & 0x0F;
  979.  
  980.     switch ( gmpChan->volColumn & 0xF0 )
  981.     {
  982.         case 0x60:
  983.             /* Volume slide down: */
  984.             return gmpSetVolume((int)gmpChan->volume - infobyte);
  985.  
  986.         case 0x70:
  987.             /* Volume slide up: */
  988.             return gmpSetVolume((int)gmpChan->volume + infobyte);
  989.  
  990.         case 0xB0:
  991.             /* Vibrato: */
  992.             return doVibrato(infobyte);
  993.  
  994.         case 0xD0:
  995.             /* Panning slide left: */
  996.             return gmpSetPanning((int)gmpChan->panning - infobyte);
  997.  
  998.         case 0xE0:
  999.             /* Panning slide right: */
  1000.             return gmpSetPanning((int)gmpChan->panning + infobyte);
  1001.  
  1002.         case 0xF0:
  1003.             /* Tone portamento: */
  1004.             return doTonePortamento(infobyte << 4);
  1005.     }
  1006.  
  1007.     /*
  1008.       0       Do nothing
  1009.     $10-$50   Set volume Value-$10
  1010.       :          :        :
  1011.       :          :        :
  1012.     $60-$6f   Volume slide down
  1013.     $70-$7f   Volume slide up
  1014.     $80-$8f   Fine volume slide down
  1015.     $90-$9f   Fine volume slide up
  1016.     $a0-$af   Set vibrato speed
  1017.     $b0-$bf   Vibrato
  1018.     $c0-$cf   Set panning
  1019.     $d0-$df   Panning slide left
  1020.     $e0-$ef   Panning slide right
  1021.     $f0-$ff   Tone porta
  1022.     */
  1023.  
  1024.     return OK;
  1025. }
  1026.  
  1027.  
  1028.  
  1029. /* Type cast for pointer to a command function: (Commands that do not use
  1030.    their info byte have been made int command(void) to avoid warnings.
  1031.    Note that even though this is safe under all supported compilers it might
  1032.    fail with some architechtures.) */ /*!!*/
  1033. #define CMD (int (*)(unsigned))
  1034.  
  1035.  
  1036.     /* Protracker playing mode tick-0 commands: */
  1037. int (*gmpTick0CommandsPT[gmpNumCommands])(unsigned infobyte) = {
  1038.     CMD &gmpCmdEmpty,                   /* no command */
  1039.     CMD &gmpCmdEmpty,                   /* arpeggio */
  1040.     CMD &gmpCmdEmpty,                   /* period slide up */
  1041.     CMD &gmpCmdEmpty,                   /* period slide down */
  1042.     CMD &gmpCmdSetTonePorta,            /* tone portamento */
  1043.     CMD &gmpCmdEmpty,                   /* vibrato */
  1044.     CMD &gmpCmdSetTonePorta,            /* tone portamento + volume slide */
  1045.     CMD &gmpCmdEmpty,                   /* vibrato + volume slide */
  1046.     CMD &gmpCmdEmpty,                   /* tremolo */
  1047.     CMD &gmpCmdSetPanning,              /* set panning (PT cmd 8) */
  1048.     CMD &gmpCmdSampleOffset,            /* set sample offset */
  1049.     CMD &gmpCmdEmpty,                   /* volume slide */
  1050.     CMD &gmpCmdPositionJump,            /* position jump */
  1051.     CMD &gmpCmdSetVolume,               /* set volume */
  1052.     CMD &gmpCmdPatternBreak,            /* pattern break (to a row) */
  1053.     CMD &gmpCmdSetSpeed,                /* set speed */
  1054.     CMD &gmpCmdSetTempo,                /* set tempo in BPM */
  1055.     CMD &gmpCmdFineSlideUp,             /* fine period slide up */
  1056.     CMD &gmpCmdFineSlideDown,           /* fine period slide down */
  1057.     CMD &gmpCmdPatternLoop,             /* pattern loop set/loop */
  1058.     CMD &gmpCmdSetPanning16,            /* set 16-point panning value */
  1059.     CMD &gmpCmdSetRetrig,               /* Protracker-style retrig note */
  1060.     CMD &gmpCmdFineVolSlideUp,          /* fine volume slide up */
  1061.     CMD &gmpCmdFineVolSlideDown,        /* fine volume slide down */
  1062.     CMD &gmpCmdNoteCut,                 /* note cut */
  1063.     CMD &gmpCmdSetNoteDelay,            /* note delay */
  1064.     CMD &gmpCmdPatternDelay,            /* pattern delay */
  1065.     CMD &gmpCmdEmpty,                   /* set master volume */
  1066.     CMD &gmpCmdEmpty,                   /* master volume slide */
  1067.     CMD &gmpCmdEmpty,                   /* S3M retrig note */
  1068.     CMD &gmpCmdMusicSync,               /* music synchronization */
  1069.     CMD &gmpCmdEmpty,                   /* extra fine period slide up */
  1070.     CMD &gmpCmdEmpty,                   /* extra fine period slide down */
  1071.     CMD &gmpCmdEmpty                    /* panning slide */
  1072.     };
  1073.  
  1074.  
  1075.  
  1076.     /* Protracker playing mode continuous commands: */
  1077. int (*gmpContCommandsPT[gmpNumCommands])(unsigned infobyte) = {
  1078.     CMD &gmpCmdEmpty,                   /* no command */
  1079.     CMD &gmpCmdArpeggio,                /* arpeggio */
  1080.     CMD &gmpCmdSlideUp,                 /* period slide up */
  1081.     CMD &gmpCmdSlideDown,               /* period slide down */
  1082.     CMD &gmpCmdTonePortamento,          /* tone portamento */
  1083.     CMD &gmpCmdVibrato,                 /* vibrato */
  1084.     CMD &gmpCmdTPortVSlide,             /* tone portamento + volume slide */
  1085.     CMD &gmpCmdVibVSlide,               /* vibrato + volume slide */
  1086.     CMD &gmpCmdEmpty,                   /* tremolo */
  1087.     CMD &gmpCmdEmpty,                   /* set panning (PT cmd 8) */
  1088.     CMD &gmpCmdEmpty,                   /* set sample offset */
  1089.     CMD &gmpCmdVolSlide,                /* volume slide */
  1090.     CMD &gmpCmdEmpty,                   /* position jump */
  1091.     CMD &gmpCmdEmpty,                   /* set volume */
  1092.     CMD &gmpCmdEmpty,                   /* pattern break (to a row) */
  1093.     CMD &gmpCmdEmpty,                   /* set speed */
  1094.     CMD &gmpCmdEmpty,                   /* set tempo in BPM */
  1095.     CMD &gmpCmdEmpty,                   /* fine period slide up */
  1096.     CMD &gmpCmdEmpty,                   /* fine period slide down */
  1097.     CMD &gmpCmdEmpty,                   /* pattern loop set/loop */
  1098.     CMD &gmpCmdEmpty,                   /* set 16-point panning value */
  1099.     CMD &gmpCmdRetrigNote,              /* Protracker-style retrig note */
  1100.     CMD &gmpCmdEmpty,                   /* fine volume slide up */
  1101.     CMD &gmpCmdEmpty,                   /* fine volume slide down */
  1102.     CMD &gmpCmdNoteCut,                 /* note cut */
  1103.     CMD &gmpCmdNoteDelay,               /* note delay */
  1104.     CMD &gmpCmdEmpty,                   /* pattern delay */
  1105.     CMD &gmpCmdEmpty,                   /* set master volume */
  1106.     CMD &gmpCmdEmpty,                   /* master volume slide */
  1107.     CMD &gmpCmdEmpty,                   /* S3M retrig note */
  1108.     CMD &gmpCmdEmpty,                   /* music synchronization */
  1109.     CMD &gmpCmdEmpty,                   /* extra fine period slide up */
  1110.     CMD &gmpCmdEmpty,                   /* extra fine period slide down */
  1111.     CMD &gmpCmdEmpty                    /* panning slide */
  1112.     };
  1113.  
  1114.  
  1115.  
  1116.  
  1117.     /* Fasttracker 2 playing mode tick-0 commands: */
  1118. int (*gmpTick0CommandsFT2[gmpNumCommands])(unsigned infobyte) = {
  1119.     CMD &gmpCmdEmpty,                   /* no command */
  1120.     CMD &gmpCmdEmpty,                   /* arpeggio */
  1121.     CMD &gmpCmdEmpty,                   /* period slide up */
  1122.     CMD &gmpCmdEmpty,                   /* period slide down */
  1123.     CMD &gmpCmdSetTonePorta,            /* tone portamento */
  1124.     CMD &gmpCmdEmpty,                   /* vibrato */
  1125.     CMD &gmpCmdSetTonePorta,            /* tone portamento + volume slide */
  1126.     CMD &gmpCmdEmpty,                   /* vibrato + volume slide */
  1127.     CMD &gmpCmdEmpty,                   /* tremolo */
  1128.     CMD &gmpCmdSetPanning,              /* set panning (PT cmd 8) */
  1129.     CMD &gmpCmdSampleOffset,            /* set sample offset */
  1130.     CMD &gmpCmdEmpty,                   /* volume slide */
  1131.     CMD &gmpCmdPositionJump,            /* position jump */
  1132.     CMD &gmpCmdSetVolume,               /* set volume */
  1133.     CMD &gmpCmdPatternBreak,            /* pattern break (to a row) */
  1134.     CMD &gmpCmdSetSpeed,                /* set speed */
  1135.     CMD &gmpCmdSetTempo,                /* set tempo in BPM */
  1136.     CMD &gmpCmdFineSlideUp,             /* fine period slide up */
  1137.     CMD &gmpCmdFineSlideDown,           /* fine period slide down */
  1138.     CMD &gmpCmdPatternLoop,             /* pattern loop set/loop */
  1139.     CMD &gmpCmdSetPanning16,            /* set 16-point panning value */
  1140.     CMD &gmpCmdSetRetrig,               /* Protracker-style retrig note */
  1141.     CMD &gmpCmdFineVolSlideUp,          /* fine volume slide up */
  1142.     CMD &gmpCmdFineVolSlideDown,        /* fine volume slide down */
  1143.     CMD &gmpCmdNoteCut,                 /* note cut */
  1144.     CMD &gmpCmdSetNoteDelay,            /* note delay */
  1145.     CMD &gmpCmdPatternDelay,            /* pattern delay */
  1146.     CMD &gmpCmdSetMVolume,              /* set master volume */
  1147.     CMD &gmpCmdEmpty,                   /* master volume slide */
  1148.     CMD &gmpCmdSetRetrig,               /* S3M retrig note */
  1149.     CMD &gmpCmdMusicSync,               /* music synchronization */
  1150.     CMD &gmpCmdExtraFineSlideUp,        /* extra fine period slide up */
  1151.     CMD &gmpCmdExtraFineSlideDown,      /* extra fine period slide down */
  1152.     CMD &gmpCmdEmpty                    /* panning slide */
  1153.     };
  1154.  
  1155.  
  1156.  
  1157.     /* Fasttracker 2 playing mode continuous commands: */
  1158. int (*gmpContCommandsFT2[gmpNumCommands])(unsigned infobyte) = {
  1159.     CMD &gmpCmdEmpty,                   /* no command */
  1160.     CMD &gmpCmdArpeggio,                /* arpeggio */
  1161.     CMD &gmpCmdSlideUp,                 /* period slide up */
  1162.     CMD &gmpCmdSlideDown,               /* period slide down */
  1163.     CMD &gmpCmdTonePortamento,          /* tone portamento */
  1164.     CMD &gmpCmdVibrato,                 /* vibrato */
  1165.     CMD &gmpCmdTPortVSlide,             /* tone portamento + volume slide */
  1166.     CMD &gmpCmdVibVSlide,               /* vibrato + volume slide */
  1167.     CMD &gmpCmdEmpty,                   /* tremolo */
  1168.     CMD &gmpCmdEmpty,                   /* set panning (PT cmd 8) */
  1169.     CMD &gmpCmdEmpty,                   /* set sample offset */
  1170.     CMD &gmpCmdVolSlide,                /* volume slide */
  1171.     CMD &gmpCmdEmpty,                   /* position jump */
  1172.     CMD &gmpCmdEmpty,                   /* set volume */
  1173.     CMD &gmpCmdEmpty,                   /* pattern break (to a row) */
  1174.     CMD &gmpCmdEmpty,                   /* set speed */
  1175.     CMD &gmpCmdEmpty,                   /* set tempo in BPM */
  1176.     CMD &gmpCmdEmpty,                   /* fine period slide up */
  1177.     CMD &gmpCmdEmpty,                   /* fine period slide down */
  1178.     CMD &gmpCmdEmpty,                   /* pattern loop set/loop */
  1179.     CMD &gmpCmdEmpty,                   /* set 16-point panning value */
  1180.     CMD &gmpCmdRetrigNote,              /* Protracker-style retrig note */
  1181.     CMD &gmpCmdEmpty,                   /* fine volume slide up */
  1182.     CMD &gmpCmdEmpty,                   /* fine volume slide down */
  1183.     CMD &gmpCmdNoteCut,                 /* note cut */
  1184.     CMD &gmpCmdNoteDelay,               /* note delay */
  1185.     CMD &gmpCmdEmpty,                   /* pattern delay */
  1186.     CMD &gmpCmdEmpty,                   /* set master volume */
  1187.     CMD &gmpCmdMVolSlide,               /* master volume slide */
  1188.     CMD &gmpCmdS3MRetrig,               /* S3M retrig note */
  1189.     CMD &gmpCmdEmpty,                   /* music synchronization */
  1190.     CMD &gmpCmdEmpty,                   /* extra fine period slide up */
  1191.     CMD &gmpCmdEmpty,                   /* extra fine period slide down */
  1192.     CMD &gmpCmdPanSlide                 /* panning slide */
  1193.     };
  1194.  
  1195.     /* Screamtracker 3 playing mode tick-0 commands: */
  1196. int (*gmpTick0CommandsST3[gmpNumCommands])(unsigned infobyte) = {
  1197.     CMD &gmpCmdEmpty,                   /* no command */
  1198.     CMD &gmpCmdEmpty,                   /* arpeggio */
  1199.     CMD &gmpCmdSlideUp,                 /* period slide up */
  1200.     CMD &gmpCmdSlideDown,               /* period slide down */
  1201.     CMD &gmpCmdSetTonePorta,            /* tone portamento */
  1202.     CMD &gmpCmdEmpty,                   /* vibrato */
  1203.     CMD &gmpCmdSetTonePorta,            /* tone portamento + volume slide */
  1204.     CMD &gmpCmdVibVSlide,               /* vibrato + volume slide */
  1205.     CMD &gmpCmdEmpty,                   /* tremolo */
  1206.     CMD &gmpCmdSetPanning,              /* set panning (PT cmd 8) */
  1207.     CMD &gmpCmdSampleOffset,            /* set sample offset */
  1208.     CMD &gmpCmdVolSlide,                /* volume slide */
  1209.     CMD &gmpCmdPositionJump,            /* position jump */
  1210.     CMD &gmpCmdSetVolume,               /* set volume */
  1211.     CMD &gmpCmdPatternBreak,            /* pattern break (to a row) */
  1212.     CMD &gmpCmdSetSpeed,                /* set speed */
  1213.     CMD &gmpCmdSetTempo,                /* set tempo in BPM */
  1214.     CMD &gmpCmdFineSlideUp,             /* fine period slide up */
  1215.     CMD &gmpCmdFineSlideDown,           /* fine period slide down */
  1216.     CMD &gmpCmdPatternLoop,             /* pattern loop set/loop */
  1217.     CMD &gmpCmdSetPanning16,            /* set 16-point panning value */
  1218.     CMD &gmpCmdSetRetrig,               /* Protracker-style retrig note */
  1219.     CMD &gmpCmdFineVolSlideUp,          /* fine volume slide up */
  1220.     CMD &gmpCmdFineVolSlideDown,        /* fine volume slide down */
  1221.     CMD &gmpCmdNoteCut,                 /* note cut */
  1222.     CMD &gmpCmdSetNoteDelay,            /* note delay */
  1223.     CMD &gmpCmdPatternDelay,            /* pattern delay */
  1224.     CMD &gmpCmdSetMVolume,              /* set master volume */
  1225.     CMD &gmpCmdEmpty,                   /* master volume slide */
  1226.     CMD &gmpCmdSetRetrig,               /* S3M retrig note */
  1227.     CMD &gmpCmdMusicSync,               /* music synchronization */
  1228.     CMD &gmpCmdEmpty,                   /* extra fine period slide up */
  1229.     CMD &gmpCmdEmpty,                   /* extra fine period slide down */
  1230.     CMD &gmpCmdEmpty                    /* panning slide */
  1231.     };
  1232.  
  1233.  
  1234.  
  1235.     /* Screamtracker 3 playing mode continuous commands: */
  1236. int (*gmpContCommandsST3[gmpNumCommands])(unsigned infobyte) = {
  1237.     CMD &gmpCmdEmpty,                   /* no command */
  1238.     CMD &gmpCmdArpeggio,                /* arpeggio */
  1239.     CMD &gmpCmdSlideUp,                 /* period slide up */
  1240.     CMD &gmpCmdSlideDown,               /* period slide down */
  1241.     CMD &gmpCmdTonePortamento,          /* tone portamento */
  1242.     CMD &gmpCmdVibrato,                 /* vibrato */
  1243.     CMD &gmpCmdTPortVSlide,             /* tone portamento + volume slide */
  1244.     CMD &gmpCmdVibVSlide,               /* vibrato + volume slide */
  1245.     CMD &gmpCmdEmpty,                   /* tremolo */
  1246.     CMD &gmpCmdEmpty,                   /* set panning (PT cmd 8) */
  1247.     CMD &gmpCmdEmpty,                   /* set sample offset */
  1248.     CMD &gmpCmdVolSlide,                /* volume slide */
  1249.     CMD &gmpCmdEmpty,                   /* position jump */
  1250.     CMD &gmpCmdEmpty,                   /* set volume */
  1251.     CMD &gmpCmdEmpty,                   /* pattern break (to a row) */
  1252.     CMD &gmpCmdEmpty,                   /* set speed */
  1253.     CMD &gmpCmdEmpty,                   /* set tempo in BPM */
  1254.     CMD &gmpCmdEmpty,                   /* fine period slide up */
  1255.     CMD &gmpCmdEmpty,                   /* fine period slide down */
  1256.     CMD &gmpCmdEmpty,                   /* pattern loop set/loop */
  1257.     CMD &gmpCmdEmpty,                   /* set 16-point panning value */
  1258.     CMD &gmpCmdRetrigNote,              /* Protracker-style retrig note */
  1259.     CMD &gmpCmdEmpty,                   /* fine volume slide up */
  1260.     CMD &gmpCmdEmpty,                   /* fine volume slide down */
  1261.     CMD &gmpCmdNoteCut,                 /* note cut */
  1262.     CMD &gmpCmdNoteDelay,               /* note delay */
  1263.     CMD &gmpCmdEmpty,                   /* pattern delay */
  1264.     CMD &gmpCmdEmpty,                   /* set master volume */
  1265.     CMD &gmpCmdEmpty,                   /* master volume slide */
  1266.     CMD &gmpCmdS3MRetrig,               /* S3M retrig note */
  1267.     CMD &gmpCmdEmpty,                   /* music synchronization */
  1268.     CMD &gmpCmdEmpty,                   /* extra fine period slide up */
  1269.     CMD &gmpCmdEmpty,                   /* extra fine period slide down */
  1270.     CMD &gmpCmdEmpty                    /* panning slide */
  1271.     };
  1272.  
  1273. /*
  1274.  * $Log: gmpcmds.c,v $
  1275.  * Revision 1.6  1997/01/16 18:41:59  pekangas
  1276.  * Changed copyright messages to Housemarque
  1277.  *
  1278.  * Revision 1.5  1996/09/01 19:14:55  pekangas
  1279.  * Changed infobytes to unsigned to keep Visual C happy
  1280.  *
  1281.  * Revision 1.4  1996/09/01 15:43:00  pekangas
  1282.  * Many changes for better FT2 compatibility, no commands use signed infobytes now
  1283.  *
  1284.  * Revision 1.3  1996/07/13 20:09:01  pekangas
  1285.  * Eliminated Visual C warnings
  1286.  *
  1287.  * Revision 1.2  1996/06/14 16:27:18  pekangas
  1288.  * Ignored all tempos below 32
  1289.  *
  1290.  * Revision 1.1  1996/05/22 20:49:33  pekangas
  1291.  * Initial revision
  1292.  *
  1293. */